package com.tarena.lbs.basic.web.service;

import com.alibaba.nacos.api.utils.StringUtils;
import com.tarena.lbs.base.common.utils.Asserts;
import com.tarena.lbs.base.protocol.exception.BusinessException;
import com.tarena.lbs.basic.web.repository.AdminRepository;
import com.tarena.lbs.basic.web.repository.UserRepository;
import com.tarena.lbs.common.passport.encoder.JwtEncoder;
import com.tarena.lbs.common.passport.enums.Roles;
import com.tarena.lbs.common.passport.principle.UserPrinciple;
import com.tarena.lbs.pojo.basic.po.AdminPO;
import com.tarena.lbs.pojo.basic.po.UserPO;
import com.tarena.lbs.pojo.passport.param.AdminLoginParam;
import com.tarena.lbs.pojo.passport.param.UserLoginParam;
import com.tarena.lbs.pojo.passport.vo.LoginVO;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
@Slf4j
public class LoginService {

    //仓储层和 持久层 的构建思路 有一个表格lbs_admin 创建一套仓储层 持久层
    @Autowired
    private AdminRepository adminRepository;
    @Autowired
    private UserRepository userRepository;
    @Autowired
    private JwtEncoder jwtEncoder;
//    spring 中创建bean对象 2种途径 第一加注解扫描Component Service Controller
//    第二种： 通过配置类 @Bean注解创建容器bean对象

    public LoginVO doAdminLogin(AdminLoginParam param) throws BusinessException {
        //入参出参 分支 都要打日志
        log.info("后台登录请求，入参：{}",param);
        //1.使用入参phone 查询lbs_admin的后台账号信息 仓储层读数据
        AdminPO adminPO = adminRepository.getAdminByPhone(param.getPhone());
        //2.判断是否存在 如果 不存在抛异常结束--业务范畴的异常 系统异常 sql错误 连接超时
        if (adminPO==null){
            log.info("后台登录请求，手机号查询不到admin");
            //手机号不存在 异常已经设计好了 BusinessException
            // 异常参数2个 1.code状态码 2.message异常提示 对应Result code message
            //Result code状态码 0表示该请求正常成功 其他表示失败
            throw new BusinessException("-2","该手机号不存在");
        }
        //3. 对比密码考虑的是 注册账号的时候 密码是否加密lmd5
        matchPassword(param.getPassword(),adminPO.getAccountPassword());
        //TODO 4.登录成功 生成JWT 如何在项目中使用Jwt
        //UserPrinciple 包含用户数据的重点信息 id 角色ADMIN SHOP USER 昵称
        /**
         * JWT 的体
         */
        UserPrinciple userPrinciple = new UserPrinciple();
        userPrinciple.setId(adminPO.getId());
        userPrinciple.setNickname(adminPO.getNickname());
        //角色是一个枚举对象 Roles.ADMIN(平台管理员)一定是admin对象 type=0 Roles.SHOP(商家账号)
        //另外一个角色是小程序登录的用户所属Roles.USER(小程序用户) admin对象type=2
        userPrinciple.setRole(adminPO.getAccountType()==0? Roles.ADMIN:Roles.SHOP);
        String jwt = jwtEncoder.generateToken(userPrinciple);
        // 5.封装LoginVO
        LoginVO vo = new LoginVO();
        vo.setJwt(jwt);
        vo.setId(adminPO.getId());
        vo.setNickname(adminPO.getNickname());
        return vo;
    }

    private void matchPassword(String password,String accountPassword) throws BusinessException {
        //入参 password 提交参数 accountPassword 数据库查询到的密码
        //使用一些工具类判断比较方便 要考虑空 和 相等
        boolean equals = StringUtils.equals(password,accountPassword);
        if (!equals){
            log.info("密码不相等，入参密码：{}，数据库密码：{}",password,accountPassword);
            //手机号不存在 异常已经设计好了 BusinessException
            // 异常参数2个 1.code状态码 2.message异常提示 对应Result code message
            //Result code状态码 0表示该请求正常成功 其他表示失败
            throw new BusinessException("-2","密码不相等");
        }
    }
    //02、小程序 用户登录
    public LoginVO doUserLogin(UserLoginParam param) throws BusinessException {
        //1.使用手机号查询用户信息
        String phone = param.getPhone();
        UserPO userPo=userRepository.getUserByPhone(phone);
        Asserts.isTrue(userPo==null,new BusinessException("-2","该手机号不存在"));
        //2.对比密码
        matchPassword(param.getPassword(),userPo.getPassword());
        //3.转换JWT
        UserPrinciple userPrinciple=new UserPrinciple();
        userPrinciple.setId(userPo.getId());
        userPrinciple.setNickname(userPo.getNickName());
        userPrinciple.setRole(Roles.USER);
        String jwt = jwtEncoder.generateToken(userPrinciple);
        //4.封装vo返回
        LoginVO vo=new LoginVO();
        vo.setJwt(jwt);
        vo.setId(userPo.getId());
        vo.setNickname(userPo.getNickName());
        return vo;
    }
}
